package com.htc.sample.lockscreencompatibility;

import java.util.Date;

import android.bluetooth.BluetoothAdapter;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.neurosky.thinkgear.TGDevice;

public class MWHeadsetController {

	BluetoothAdapter bluetoothAdapter;
	
	TextView tv;	
	Button b;
	
	TGDevice tgDevice;
	final boolean rawEnabled = false;
	
	public static int LOGLEVEL = 1;
	public static boolean WARN = LOGLEVEL > 1;
	public static boolean DEBUG = LOGLEVEL > 0;
	public static String TAG = "HEADSET MSG:";
	
	private static double USER_HARD_BLINK_MIN_INTENSITY;
	private static double USER_ATTENTION_MAX_INTENSITY;
	private static double USER_MEDITATION_MAX_INTENSITY;
	
	private static double ATTENTION_INTENSITY_SCALE = 10.0;
	private static double MEDITATION_INTENSITY_SCALE = 10.0;
	
	private boolean hasGoodSignal = false;

	private final boolean isDebugMode = false;
	private final boolean isTextViewEnabled = false;

	
	private enum person {JIM, JEANCARL};
	private person currentUser = person.JIM;
	
	public boolean initiateHeadsetConnection(Handler handler){
    	   
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        
        if(bluetoothAdapter == null) {
        	// Alert user that Bluetooth is not available
        	addMessage("Bluetooth not available");
        	return false;
        }else {
        	/* create the TGDevice */
        	/*int i = 0;
        	while(i < 5)
        	{
        		Toast.makeText(this, "Found bluetooth adapter in else block " + i + " times.", Toast.LENGTH_LONG).show();
        		i++;
        	}
        	*/
        	tgDevice = new TGDevice(bluetoothAdapter, handler);
        	
        	this.setUserIntensitySettings(currentUser);
        	return true;
        }
    }
	
    public void processMessage(Message msg){
    	int intensity = msg.arg1;
    	String msgString = "";
    	
    	switch (msg.what) {
        case TGDevice.MSG_STATE_CHANGE:
            switch (intensity) {
                case TGDevice.STATE_IDLE:
                    break;
                case TGDevice.STATE_CONNECTING:		                	
                	msgString = "Connecting...\n";
                	break;		                    
                case TGDevice.STATE_CONNECTED:
                	msgString = "Connected.\n";
                	tgDevice.start();
                    break;
                case TGDevice.STATE_NOT_FOUND:
                	msgString = "Can't find MindWave\n";
                	break;
                case TGDevice.STATE_NOT_PAIRED:
                	msgString = "not paired with MindWave\n";
                	break;
                case TGDevice.STATE_DISCONNECTED:
                	
                	tgDevice.stop();
                	msgString = "Disconnected from MindWave\n";
            }
            
            // There is some issue with addMessage in the case block above so this is a hack
            if(isTextViewEnabled)tv.append(msgString);
            else addMessage(msgString);
            
            break;
        case TGDevice.MSG_POOR_SIGNAL:
        		//signal = msg.arg1;
        		if(intensity != 0) {
        			addMessage("PoorSignal: " + intensity + "\n");
        			setHasGoodSignal(false);            			
        		}
        		else {
        			setHasGoodSignal(true);
        		}
            break;
        case TGDevice.MSG_RAW_DATA:	  
        		//raw1 = msg.arg1;
        		//tv.append("Got raw: " + msg.arg1 + "\n");
        	break;
        case TGDevice.MSG_HEART_RATE:
    		addMessage("Heart rate: " + intensity + "\n");
            break;
        case TGDevice.MSG_ATTENTION:
        		//att = msg.arg1;
        		//tv.append("Attention: " + intensity + "\n");
        		//Log.v("HelloA", "Attention: " + att + "\n");
        		processAttentionEvent(intensity);
        	break;
        case TGDevice.MSG_MEDITATION:
        		processMeditationEvent(intensity);
        	break;
        case TGDevice.MSG_BLINK:
        		//tv.append("Blink: " + msg.arg1 + "\n");
        		processBlinkEvent(intensity);
        		
        	break;
        case TGDevice.MSG_RAW_COUNT:
        		//tv.append("Raw Count: " + msg.arg1 + "\n");
        	break;
        case TGDevice.MSG_LOW_BATTERY:
        	addMessage("Low battery!");
        	break;
        case TGDevice.MSG_RAW_MULTI:
        	//TGRawMulti rawM = (TGRawMulti)msg.obj;
        	//tv.append("Raw1: " + rawM.ch1 + "\nRaw2: " + rawM.ch2);
        default:
        	break;
    }
    }
    
    // method to process a blink event
    private void processBlinkEvent(int intensity) {
    	// If there is not a good signal do not send any events
    	if(!hasGoodSignal()) return;
    	
    	if(isDebugMode){
	    	
	    	if(intensity > USER_HARD_BLINK_MIN_INTENSITY) {
	    		addMessage("Hard Blink for " + currentUser + ": " + intensity + "\n");
	    	}
	    	else{
	    		addMessage("Blink: " + intensity + "\n");
	    	}
	    	
    	}
    	else{
    		if(intensity > USER_HARD_BLINK_MIN_INTENSITY) {
    			HeadsetDataCapture.setLatestHardBlinkEvent(createEvent(MWEventType.HARD_BLINK, 10));
    			addMessage(HeadsetDataCapture.getLatestHardBlinkEvent().toString() + "\n");
    		}
    	}
    }
    
    // method to process a attention event
    private void processAttentionEvent(int intensity) {
    	// If there is not a good signal do not send any events
    	if(!hasGoodSignal()) return;
    	long scaledIntensity = Math.round(ATTENTION_INTENSITY_SCALE * intensity/USER_ATTENTION_MAX_INTENSITY);
		if(scaledIntensity > ATTENTION_INTENSITY_SCALE) scaledIntensity = (new Double(ATTENTION_INTENSITY_SCALE)).longValue();
    	if(isDebugMode){
    		addMessage("Attention: " + intensity);
        	addMessage(" Scaled Attention for " + currentUser + ": " + scaledIntensity + "\n");
    	}
    	else{

    		HeadsetDataCapture.setLatestAttentionEvent(createEvent(MWEventType.ATTENTION, scaledIntensity));
    		addMessage(HeadsetDataCapture.getLatestAttentionEvent().toString() + "\n");
    	}
    	
    
    }
    
    // method to process a attention event
    private void processMeditationEvent(int intensity) {
    	// If there is not a good signal do not send any events
    	if(!hasGoodSignal()) return;
    	
    	long scaledIntensity = Math.round(MEDITATION_INTENSITY_SCALE * intensity/USER_MEDITATION_MAX_INTENSITY);
    	if(scaledIntensity > MEDITATION_INTENSITY_SCALE) scaledIntensity = (new Double(MEDITATION_INTENSITY_SCALE)).longValue();
    	if(isDebugMode){
	    	addMessage("Meditation: " + intensity);
	    	addMessage(" Scaled Meditation for " + currentUser + ": " + scaledIntensity + "\n");
    	}
    	else{
    		HeadsetDataCapture.setLatestMeditationEvent(createEvent(MWEventType.MEDITATION, scaledIntensity));

    		addMessage(HeadsetDataCapture.getLatestMeditationEvent().toString() + "\n");
    		
    	}
    
    }
    
    
    
	// method to append a string to a TextView as a new line
	// and scroll to the bottom if needed
	private void addMessage(String msg){
		// Log all messages
	    if (DEBUG) Log.v(TAG, "DEBUG: " + msg);
/*		
		if(isTextViewEnabled) {
			TextView view = this.getTextView();
			if(view.getLineCount() > 15) view.setLines(15);
			
			// append the new string
			 view.append(msg);
		     // find the amount we need to scroll.  This works by
		     // asking the TextView's internal layout for the position
		     // of the final line and then subtracting the TextView's height
		     final int scrollAmount = view.getLayout().getLineTop(view.getLineCount()) -view.getHeight();
		     //final int scrollAmount = view.getLayout().getLineBottom(view.getLineCount()) -view.getHeight();
		     // if there is no need to scroll, scrollAmount will be <=0
		     if(scrollAmount>0)
		    	 view.scrollTo(0, scrollAmount);
		     else
		    	 view.scrollTo(0,0);

    	}
*/     
	}
	
	
	public void openHeadsetDataPipeline() {
    	if(this.getTgDevice().getState() != TGDevice.STATE_CONNECTING && 
    			this.getTgDevice().getState() != TGDevice.STATE_CONNECTED)
    		this.getTgDevice().connect(this.rawEnabled);   

    }
	
	private void setUserIntensitySettings(person name){
		
		if(name == person.JIM){
			USER_HARD_BLINK_MIN_INTENSITY = 45.0;
			USER_ATTENTION_MAX_INTENSITY = 90.0;
			USER_MEDITATION_MAX_INTENSITY = 90.0;
		}
		else{
			USER_HARD_BLINK_MIN_INTENSITY = 40.0;
			USER_ATTENTION_MAX_INTENSITY = 100.0;
			USER_MEDITATION_MAX_INTENSITY = 100.0;
		}
		
	}

	private boolean hasGoodSignal() {
		return hasGoodSignal;
	}

	private void setHasGoodSignal(boolean hasGoodSignal) {
		this.hasGoodSignal = hasGoodSignal;
	}
	
	private MWEvent createEvent(MWEventType eventType, long intensity){
		
		MWEvent event = new MWEvent();
		event.setEventTime(new Date());
		event.setType(eventType);
		event.setIntensity(intensity);
		
		return event;
		
	}
	

	private void sentEvent(MWEvent event){
		addMessage("Sent event: " + event.toString() + "\n");
		
	}

	public TGDevice getTgDevice() {
		return tgDevice;
	}

	public void setTgDevice(TGDevice tgDevice) {
		this.tgDevice = tgDevice;
	}
}
